package com.homelock.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.homelock.constants.OpmodeEnum;
import com.homelock.constants.UnlockAttributeEnum;
import com.homelock.domain.UserUnlockPostForm;
import com.homelock.entity.HlDevUserUnlock;
import com.homelock.entity.HlDevUserUnlockExample;
import com.homelock.entity.HlDevUserUnlockExample.Criteria;
import com.homelock.mapper.HlDevUserUnlockMapper;
import com.pi.base.enumerate.record.RecordState;
import com.pi.base.exception.ServiceException;

@Service
public class HlDevUserUnlockService {

    private static final Logger logger = LoggerFactory.getLogger(HlDevUserUnlockService.class);

    private HlDevUserUnlockMapper devUserUnlockMapper;
    
    private LockTemporaryPwdService lockTemporaryPwdService;

    @Autowired
    public HlDevUserUnlockService(HlDevUserUnlockMapper devUserUnlockMapper,LockTemporaryPwdService lockTemporaryPwdService) {
        Assert.notNull(devUserUnlockMapper, "锁具指纹密码数据服务为空");
        Assert.notNull(lockTemporaryPwdService, "锁具临时密码服务为空");
        this.devUserUnlockMapper = devUserUnlockMapper;
        this.lockTemporaryPwdService = lockTemporaryPwdService;
    }

    /**
     * 添加锁的指纹/密码
     * 
     * @param unlockType
     * @param userId
     * @param unlockId
     * @param unlockName
     * @return
     */
    public Long addUserUnlock(UserUnlockPostForm userUnlockPostForm) {
        OpmodeEnum opmodeEnum = OpmodeEnum.getOpmodeEnum(userUnlockPostForm.getOpmode());
        UnlockAttributeEnum unlockAttributeEnum = UnlockAttributeEnum
                .getUnlockAttributeEnum(userUnlockPostForm.getUnlockAttribute());
        // 校验用户是否存在
        // 校验设备是否存在
        HlDevUserUnlock record = new HlDevUserUnlock();
        Date date = new Date();
        record.setDevId(userUnlockPostForm.getDevId());
        record.setDevUserId(userUnlockPostForm.getUserId());
        record.setUnlockType(opmodeEnum.getOpmode());
        record.setUnlockId(userUnlockPostForm.getUnlockId());
        record.setUnlockName(userUnlockPostForm.getUnlockName());
        record.setUnlockPhase((byte) 2);
        record.setVersion((long) 1);
        record.setCreateDate(date);
        record.setUpdateDate(date);
        record.setState(RecordState.STATE_NORMAL.getState());
        record.setUnlockAttribute(null != unlockAttributeEnum ? unlockAttributeEnum.getAttribute()
                : UnlockAttributeEnum.NORMAL.getAttribute());
        devUserUnlockMapper.insertSelective(record);
        return record.getId();
    }

    /**
     * 删除用户下的指纹密码
     * 
     * @param unlockType
     * @param userId
     * @param unlockId
     */
    public void removeLockUser(int unlockType, Long userId, String unlockId) {
        HlDevUserUnlock lockUserInfo = getLockUseUnlockInfo(unlockType, userId, unlockId);
        devUserUnlockMapper.deleteByPrimaryKey(lockUserInfo.getId());
    }

    /**
     * 清空用户下的所有记录
     * 
     * @param userId
     */
    public void removeUserUnlock(Long devId, Long opmodeId) {
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        example.createCriteria().andIdEqualTo(opmodeId).andDevIdEqualTo(devId);
        devUserUnlockMapper.deleteByExample(example);
    }

    /**
     * 更新密码/指纹名称
     * 
     * @param unlockType
     * @param userId
     * @param unlockId
     * @param unlockName
     */

    public void updateUserUnlockName(Long devId, Long opmodeId, String unlockName) {
        if(StringUtils.isBlank(unlockName) || null ==devId || null == opmodeId) {
          throw new ServiceException("参数错误");
        }
        HlDevUserUnlock devUserUnlock = validAndGetUserUnlockInfo(devId, opmodeId);
        HlDevUserUnlock record = new HlDevUserUnlock();
        record.setUnlockName(unlockName);
        record.setId(devUserUnlock.getId());
        record.setVersion(devUserUnlock.getVersion() + 1);
        record.setUpdateDate(new Date());
        devUserUnlockMapper.updateByPrimaryKeySelective(record);
    }

    /**
     * 更新密码/指纹名称
     * 
     * @param unlockType
     * @param userId
     * @param unlockId
     * @param unlockName
     */

    public void updateUserUnlockPhase(Long opmodeId, OpmodeEnum t, int phase) {
        HlDevUserUnlock record = new HlDevUserUnlock();
        record.setUnlockPhase((byte) phase);
        record.setId(opmodeId);
        record.setUpdateDate(new Date());
        devUserUnlockMapper.updateByPrimaryKeySelective(record);
    }

    public void switchAlarmAttribute(Long devId, Long opmodeId, Integer attribute) {
        HlDevUserUnlock devUserUnlock = devUserUnlockMapper.selectByPrimaryKey(opmodeId);
        if (null == devUserUnlock || !devUserUnlock.getState()) {
            throw new ServiceException("开锁方式已失效或不存在");
        }
        OpmodeEnum opmodeEnum = OpmodeEnum.getOpmodeEnum(devUserUnlock.getUnlockType().intValue());
        if (OpmodeEnum.UNLOCK_FINGER != opmodeEnum) {
            throw new ServiceException("不支持指纹之外的开门方式");
        }
        UnlockAttributeEnum unlockAttributeEnum = UnlockAttributeEnum.getUnlockAttributeEnum(attribute);
        if (null == attribute) {
            throw new ServiceException("开门方式属性不正确");
        }
        if (devUserUnlock.getUnlockAttribute() == attribute.byteValue()) {
            throw new ServiceException("不能重复设置相同属性");
        }
        HlDevUserUnlock record = new HlDevUserUnlock();
        record.setId(devUserUnlock.getId());
        record.setUpdateDate(new Date());
        record.setVersion(devUserUnlock.getVersion() + 1);
        record.setUnlockAttribute(unlockAttributeEnum.getAttribute());
        devUserUnlockMapper.updateByPrimaryKeySelective(record);
    }

    /**
     * 获取用户的某个密码指纹
     * 
     * @param unlockType
     * @param userId
     * @param unlockId
     * @return
     */
    public HlDevUserUnlock getLockUseUnlockInfo(int unlockType, Long userId, String unlockId) {
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        example.createCriteria().andDevUserIdEqualTo(userId).andUnlockIdEqualTo(unlockId)
                .andUnlockTypeEqualTo((byte) unlockType);
        List<HlDevUserUnlock> devUserist = devUserUnlockMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(devUserist)) {
            throw new ServiceException("LOCK_USER_NOT_EXIST");
        }
        return devUserist.get(0);
    }

    /**
     * 获取用户下面的全部的指纹/密码
     * 
     * @param unlockType
     * @param userId
     * @return
     */
    public List<HlDevUserUnlock> getLockUseUnlockInfo(int unlockType, Long userId) {
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        example.createCriteria().andDevUserIdEqualTo(userId).andUnlockTypeEqualTo((byte) unlockType);
        List<HlDevUserUnlock> devUserist = devUserUnlockMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(devUserist)) {
            throw new ServiceException("LOCK_USER_UNLOCK_NOT_EXIST");
        }
        return devUserist;
    }

    private HlDevUserUnlock validAndGetUserUnlockInfo(Long devId, Long opmodeId) {
        HlDevUserUnlock userUnlockInfo = getUserUnlockInfoIfExist(opmodeId);
        if (null == userUnlockInfo || userUnlockInfo.getDevId().longValue() != devId) {
            throw new ServiceException("LOCK_USER_UNLOCK_NOT_EXIST");
        }
        return userUnlockInfo;
    }

    private HlDevUserUnlock getUserUnlockInfoIfExist(Long opmodeId) {
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        example.createCriteria().andIdEqualTo(opmodeId);
        return devUserUnlockMapper.selectByPrimaryKey(opmodeId);
    }

    public List<HlDevUserUnlock> queryUnlockInfo(Long devId, Integer opmode, Long userId) {
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        Criteria criteria = example.createCriteria();
        criteria.andDevIdEqualTo(devId);
        criteria.andUnlockTypeEqualTo(opmode.byteValue());
        if (null != userId) {
            criteria.andDevUserIdEqualTo(userId);
        }
        criteria.andStateEqualTo(RecordState.STATE_NORMAL.getState());
        List<HlDevUserUnlock> devUnlockList = devUserUnlockMapper.selectByExample(example);
        return devUnlockList;
    }

    public void updateUserUnlockId(Long opmodeId, Integer unlockId, OpmodeEnum opmodeEnum) {
        HlDevUserUnlock userUnlock = devUserUnlockMapper.selectByPrimaryKey(opmodeId);
        if(null == userUnlock || opmodeEnum.getOpmode() != userUnlock.getUnlockType()){
            throw new ServiceException("UNLOCK_NOT_EXIST");
        }
        if(StringUtils.isNotBlank(userUnlock.getUnlockId()) && Integer.parseInt(userUnlock.getUnlockId()) != 0){
            logger.error("开锁方式: {} 更新错误， 序号: {}， 编号: {}", opmodeEnum.getOpmode(), opmodeId, unlockId);
            return;
        }
        HlDevUserUnlock record = new HlDevUserUnlock();
        record.setId(opmodeId);
        record.setUnlockId(unlockId.toString());
        devUserUnlockMapper.updateByPrimaryKeySelective(record);
    }

    public void clearByDevId(Long devId) {
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        example.createCriteria()
        .andDevIdEqualTo(devId)
        .andStateEqualTo(RecordState.STATE_NORMAL.getState());
        List<HlDevUserUnlock> unlockList = devUserUnlockMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(unlockList)){
            return;
        }
        List<Long> ids = new ArrayList<>(unlockList.size());
        List<Long> tempPwdIds = new ArrayList<>(unlockList.size());
        for(HlDevUserUnlock userUnlock :unlockList){
            ids.add(userUnlock.getId());
            if(OpmodeEnum.UNLOCK_TPWD.getOpmode() == userUnlock.getUnlockType()){
                tempPwdIds.add(userUnlock.getId());
            }
        }
        example.clear();
        HlDevUserUnlock record = new HlDevUserUnlock();
        example.createCriteria().andIdIn(ids);
        record.setState(RecordState.STATE_DELETE.getState());
        devUserUnlockMapper.updateByExampleSelective(record, example);
        if(CollectionUtils.isEmpty(tempPwdIds)){
            return;
        }
        lockTemporaryPwdService.clearByTempPwdIds(tempPwdIds);
    }

    public HlDevUserUnlock queryByDevIdAndUnlockTypeAndUnlockId(Long devId,byte unlockType,String unlockId){
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        example.createCriteria()
                .andDevIdEqualTo(devId)
                .andUnlockTypeEqualTo(unlockType)
                .andUnlockIdEqualTo(unlockId)
                .andStateEqualTo(RecordState.STATE_NORMAL.getState());
        List<HlDevUserUnlock> list = devUserUnlockMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    public HlDevUserUnlock queryById(Long id){
        return devUserUnlockMapper.selectByPrimaryKey(id);
    }
    
    public int countByDevId(Long devId, OpmodeEnum opmode) {
        if(null == devId || devId <= 0) {
            throw new ServiceException("统计的编号为空");
        }
        if(null == opmode) {
            throw new ServiceException("开锁方式类型为空");
        }
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        Criteria criteria = example.createCriteria();
        criteria.andDevIdEqualTo(devId);
        if(null != opmode) {
            criteria.andUnlockTypeEqualTo(opmode.getOpmode());
        }
        criteria.andStateEqualTo(RecordState.STATE_NORMAL.getState());
        return devUserUnlockMapper.countByExample(example);
    }


    /**
     * 振兴锁新增或者删除
     * @param unlock
     * @return
     */
    public int insertOrUpdate(HlDevUserUnlock unlock){
        HlDevUserUnlock  exist = findOneByDevIdAnUnlockIdAndStatusTrue(unlock.getDevId(),unlock.getUnlockId());
        Date date = new Date();
        if(null == exist){
            unlock.setCreateDate(date);
            unlock.setUpdateDate(date);
            unlock.setState(RecordState.STATE_NORMAL.getState());
            unlock.setVersion(1L);
            // 新增
            return devUserUnlockMapper.insertSelective(unlock);
        }
        // 更新
        unlock.setVersion(exist.getVersion()+1);
        unlock.setUpdateDate(date);
        unlock.setId(exist.getId());
        return devUserUnlockMapper.updateByPrimaryKeySelective(unlock);
    }

    /**
     * 振兴锁删除
     * 假删，只修改状态
     * @param unlock
     * @return
     */
    public int deleteByDevIdAndUnlockId(HlDevUserUnlock unlock){
        HlDevUserUnlock exist = findOneByDevIdAnUnlockIdAndStatusTrue(unlock.getDevId(),unlock.getUnlockId());
        if(null == exist){
            logger.error("需要删除的数据本地数据库不存在：设备id:{},用户类型：{}，用户id:{}", unlock.getDevId(),unlock.getUnlockType(),unlock.getUnlockId());
            return 0;
        }
        HlDevUserUnlock update = new HlDevUserUnlock();
        update.setId(exist.getId());
        update.setVersion(exist.getVersion()+1);
        update.setUpdateDate(new Date());
        update.setState(RecordState.STATE_DELETE.getState());
        return devUserUnlockMapper.updateByPrimaryKeySelective(update);
    }

    /**
     * 根据设备id unlockId 查询
     * @param devId
     * @param unlockId
     * @return
     */
    public HlDevUserUnlock  findOneByDevIdAnUnlockIdAndStatusTrue(Long devId,String unlockId ){
        HlDevUserUnlockExample example = new HlDevUserUnlockExample();
        example.createCriteria().andDevIdEqualTo(devId).andUnlockIdEqualTo(unlockId).
                andStateEqualTo(RecordState.STATE_NORMAL.getState());
        List<HlDevUserUnlock> list = devUserUnlockMapper.selectByExample(example);
        return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }
}
